package com.customview;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.util.AttributeSet;



import java.util.ArrayList;

import static android.graphics.Shader.TileMode.CLAMP;

public class LinearStatisticalTableView extends android.view.View {
    private final int totalY_Marks = 6;
    private final float maxValue = 100f;

    private final int backgroundColor = Color.parseColor("#393948");

    private float valueLineWidth;

    private Paint mDottedLinePaint;
    private Paint mValueLinePaint01;
    private Paint mValueLinePaint02;
    private Paint mCoverPaint;

    private Paint mTextPaintX;
    private Paint mTextPaintY;

    private float paddingTopAndBottom;
    private float paddingLeft;

    private RectF rectF = new RectF();

    private float textHeightX;
    private float textHeightY;

    private boolean isInited;
    private boolean isRunning;

    private Object lock = new Object();

    private ArrayList<ValueObject> values = new ArrayList<>();

    public LinearStatisticalTableView(Context context) {
        super(context);
    }

    public LinearStatisticalTableView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public LinearStatisticalTableView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {
        mDottedLinePaint = new Paint();
        mDottedLinePaint.setAntiAlias(true);
        mDottedLinePaint.setColor(Color.parseColor("#979797"));//虚线
        mDottedLinePaint.setStyle(Paint.Style.STROKE);
        mDottedLinePaint.setStrokeWidth(3);
        mDottedLinePaint.setPathEffect(new DashPathEffect(new float[]{30, 20}, 0));

        mValueLinePaint01 = new Paint();
        mValueLinePaint01.setAntiAlias(true);
        mValueLinePaint01.setColor(Color.parseColor("#2CFFF8"));
        mValueLinePaint01.setStyle(Paint.Style.FILL);
        mValueLinePaint01.setShadowLayer(10,-5,5, Color.BLACK);
//        mValueLinePaint01.setShader(new LinearGradient(0f,getHeight() - paddingTopAndBottom, 0,paddingTopAndBottom,new int[]{0xFF19D5CF,0xFF34B5E5},null, CLAMP));

        mValueLinePaint02 = new Paint();
        mValueLinePaint02.setAntiAlias(true);
        mValueLinePaint02.setColor(Color.parseColor("#2693FF"));
        mValueLinePaint02.setStyle(Paint.Style.FILL);
        mValueLinePaint02.setShadowLayer(10,-5,5, Color.BLACK);

//        mValueLinePaint02.setShader(new LinearGradient(0f,getHeight() - paddingTopAndBottom, 0,paddingTopAndBottom,new int[]{0xFFA886CE,0xFF5F78F2},null, CLAMP));

        mCoverPaint = new Paint();
        mCoverPaint.setAntiAlias(true);
        mCoverPaint.setColor(backgroundColor);
        mCoverPaint.setStyle(Paint.Style.FILL);

        mTextPaintX = new Paint();
        mTextPaintX.setAntiAlias(true);
        mTextPaintX.setColor(Color.WHITE);
        mTextPaintX.setStyle(Paint.Style.FILL);
        mTextPaintX.setTextSize(40);
        mTextPaintX.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/montserrat_medium.ttf"));

        Paint.FontMetrics fontMetricsX = mTextPaintX.getFontMetrics();
//        float height1 = fontMetricsX.descent - fontMetricsX.ascent;
        textHeightX = fontMetricsX.bottom - fontMetricsX.top;

        mTextPaintY = new Paint();
        mTextPaintY.setAntiAlias(true);
        mTextPaintY.setColor(Color.WHITE);
        mTextPaintY.setStyle(Paint.Style.FILL);
        mTextPaintY.setTextSize(30);
        mTextPaintY.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "font/montserrat_medium.ttf"));

        Paint.FontMetrics fontMetricsY = mTextPaintY.getFontMetrics();
        textHeightY = fontMetricsY.descent - fontMetricsY.ascent;
//        textHeightY = fontMetricsY.bottom - fontMetricsY.top;


        paddingTopAndBottom = getHeight() / 10f;
        paddingLeft = getWidth() * 0.15f;
        valueLineWidth = getWidth() * 10 / 345f;

        setBackgroundColor(backgroundColor);

        testValues();
    }

    public void testValues(){
        values.clear();
        values.add(new ValueObject(40f, 50f));
        values.add(new ValueObject(66f, 83f));
        values.add(new ValueObject(90f, 89f));
        values.add(new ValueObject(40f, 50f));
        values.add(new ValueObject(66f, 83f));
        values.add(new ValueObject(40f, 50f));
        values.add(new ValueObject(90f, 89f));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (!isInited) {
            init();
            isInited = true;
        }

        drawTableBackground(canvas);

        synchronized (lock) {
            drawLinearStatistical(canvas);
        }
    }

    private void drawTableBackground(Canvas canvas){
        float baseY = getHeight() - paddingTopAndBottom;
        float heightUnit = (getHeight() - paddingTopAndBottom * 2) / (totalY_Marks - 1);

        for(int i=0; i<totalY_Marks; i++){
            canvas.drawLine(paddingLeft, baseY - heightUnit * i, getWidth(), baseY - heightUnit * i, mDottedLinePaint);

            canvas.drawText(getTextY(i), paddingLeft - mTextPaintY.measureText("100") * 1.5f, baseY - heightUnit * i + textHeightY / 4, mTextPaintY);
        }
    }

    private String getTextY(int position){
        switch (position){
            case 0:
                return "0";
            case 1:
                return "20";
            case 2:
                return "40";
            case 3:
                return "60";
            case 4:
                return "80";
            default:
                return "100";
        }
    }

    private void drawLinearStatistical(Canvas canvas){
        float spaceX = 20;
        float baseX = paddingLeft + spaceX + valueLineWidth * 1.25f;
        float widthUnit = (getWidth() - baseX - spaceX - valueLineWidth * 1.25f) / (values.size() - 1);

        float maxValueLineHeight = getHeight() - paddingTopAndBottom * 2;

        for(int i=0; i<values.size(); i++){
            float centerX = baseX + widthUnit * i;

            float valueLineHeight = maxValueLineHeight * values.get(i).value00 / maxValue;
            rectF.set(centerX - valueLineWidth * 0.8f, getHeight() - paddingTopAndBottom - valueLineHeight,
                    centerX - valueLineWidth * 0.25f, getHeight() - paddingTopAndBottom );
            canvas.drawRoundRect(rectF, valueLineWidth, valueLineWidth, mValueLinePaint01);

            valueLineHeight = maxValueLineHeight * values.get(i).value01 / maxValue;
            rectF.set(centerX + valueLineWidth * 0.25f, getHeight() - paddingTopAndBottom - valueLineHeight,
                    centerX + valueLineWidth * 0.8f, getHeight() - paddingTopAndBottom );
            canvas.drawRoundRect(rectF, valueLineWidth, valueLineWidth, mValueLinePaint02);

            /**
             * 覆盖圆角矩形下面的圆角
             */
 /*           float top = getHeight() - paddingTopAndBottom + mDottedLinePaint.getStrokeWidth();
            rectF.set(paddingLeft, top, getWidth(), getHeight());
            canvas.drawRect(rectF,mCoverPaint);*/
        }

        /**
         * X 轴刻度文字
         */
        for(int i=0; i<values.size(); i++) {
            float centerX = baseX + widthUnit * i;

            String str = getTextX(i);
            float textWidth = mTextPaintX.measureText(str);
            canvas.drawText(str, centerX - textWidth / 2, getHeight() - textHeightX / 4, mTextPaintX);
        }
    }

    private String getTextX(int position){
        switch (position){
            case 0:
                return "一";
            case 1:
                return "二";
            case 2:
                return "三";
            case 3:
                return "四";
            case 4:
                return "五";
            case 5:
                return "六";
            default:
                return "天";
        }
    }

    public static class ValueObject{

        float value00;
        float value01;

        public ValueObject(float value00, float value01) {
            this.value00 = value00;
            this.value01 = value01;
        }

        float getMaxValue(){
            return Math.max(value00, value01);
        }
    }

    public void addValues(final ArrayList<ValueObject> valueObjects, boolean animation){
        if(!animation){
            values.clear();
            values.addAll(valueObjects);
            postInvalidate();
        }
        else{
            if(isRunning){
                return;
            }

            new Thread(){
                public void run(){
                    isRunning = true;

                    float maxValue = 0f;

                    ArrayList<ValueObject> temps = new ArrayList<>();
                    for (ValueObject valueObject : valueObjects){
                        temps.add(new ValueObject(0f, 0f));
                        maxValue = Math.max(maxValue, valueObject.getMaxValue());
                    }

                    postInvalidate();

                    boolean flag = true;
                    float increase = 0.5f;

                    while (flag){

                        for (int i=0; i<temps.size(); i++){
                            ValueObject object = temps.get(i);
                            if(object.value00 < valueObjects.get(i).value00){
                                object.value00 += increase;
                            }
                            else if(object.value00 < maxValue){
                                object.value00 = valueObjects.get(i).value00;
                            }
                            else{
                                flag = false;
                            }

                            if(object.value01 < valueObjects.get(i).value01){
                                object.value01 += increase;
                            }
                            else if(object.value01 < maxValue){
                                object.value01 = valueObjects.get(i).value01;
                            }
                            else{
                                flag = false;
                            }
                        }

                        synchronized (lock) {
                            values.clear();
                            values.addAll(temps);
                        }

                        postInvalidate();

                        SystemClock.sleep(2);
                    }

                    values.clear();
                    values.addAll(valueObjects);
                    postInvalidate();

                    isRunning = false;
                }
            }.start();
        }
    }

    public void stopProgress(){
        isRunning = false;
    }
}
